package com.zf.yichat.service.impl;

import com.github.pagehelper.PageHelper;
import com.zf.yichat.dto.SaleChartItem;
import com.zf.yichat.im.mapper.RcGroupsDismissMapper;
import com.zf.yichat.im.mapper.RcGroupsMapper;
import com.zf.yichat.mapper.*;
import com.zf.yichat.model.*;
import com.zf.yichat.service.BalanceService;
import com.zf.yichat.service.PayService;
import com.zf.yichat.service.PushService;
import com.zf.yichat.service.XsPayService;
import com.zf.yichat.service.config.RedisService;
import com.zf.yichat.service.dto.BalanceListDto;
import com.zf.yichat.utils.YiChatMsgCode;
import com.zf.yichat.utils.common.*;
import com.zf.yichat.utils.response.FsPage;
import com.zf.yichat.utils.response.FsResponse;
import com.zf.yichat.utils.response.FsResponseGen;
import com.zf.yichat.vo.BalanceType;
import com.zf.yichat.vo.IntegralType;
import com.zf.yichat.vo.PayType;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.hibernate.validator.internal.util.Contracts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 一句话描述功能
 *
 * @author fengsong
 * @date create in 16:52 2019/6/10 2019
 */
@Service
public class BalanceServiceImpl implements BalanceService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RcGroupsMapper groupsMapper;
    @Autowired
    private RcGroupsDismissMapper groupsDismissMapper;
    @Autowired
    private BalanceService balanceService;
    @Resource
    private UserBankMapper userBankMapper;
    @Resource
    private RedisService redisService;

    @Autowired
    private UserIntegralDetailMapper userIntegralDetailMapper;

    @Autowired
    private UserBalanceMapper userBalanceMapper;

    @Autowired
    private UserBalanceDetailMapper userBalanceDetailMapper;

    @Autowired
    private UserWithdrawMapper userWithdrawMapper;

    @Autowired
    private UserTradeMapper userTradeMapper;

    @Autowired
    private PushService pushService;

    @Autowired
    private PayService payService;

    @Autowired
    private XsPayService xsPayService;

    @Autowired
    private PacketMapper packetMapper;

    @Override
    public void create(Long userId) {
        UserBalance balance = new UserBalance();
        balance.setBalance(BigDecimal.ZERO);
        balance.setUserId(userId);
        userBalanceMapper.insertSelective(balance);

    }

    @Override
    public void update(Long userId, BalanceType type, BigDecimal money, Long referId, String memo) {


        switch (type) {
            case ADD:
            case BACK_ADD:
            case RECEIVE_PACKET:
                //添加可用余额  总余额+ 冻结-- 可用+
            case SIGN:
                //签到积分充值  总余额+ 冻结-- 可用+
            case PACKET_SALE_TERMINATE_BACK:
            case PACKET_SALE_GET:
            case PACKET_SALE_GET_FREEZE_OWNER_END:
            case MISSION_COMMISSION_REFUSE:
            case MISSION_REFUSE:
            case VIDEO_PLAY:
            case VIDEO_PACKET:
            case VIP_PACKET_RECEIVE:
            case VIDEO_COMMENT:
            case VIDEO_PRAISE:
            case VIDEO_PUBLISH:
            case USER_INVITE:
            case PACKET_FANLI_GET:
            case PACKET_FANLI_INVITE_GET:
            case INTEGRAL_EXCHANGE_BALANCE: // 积分兑换余额
                //领取淘宝客等返利（审核通过）   总余额+ 冻结-- 可用+
                //邀请用户 总余额+ 冻结-- 可用+
                //发布视频   总余额+ 冻结 -- 可用+
                //点赞视频奖励   总余额+ 冻结 -- 可用+
                //评论视频奖励   总余额+ 冻结 -- 可用+
                //领取视频红包   总余额+ 冻结 -- 可用+
                //看视频奖励   总余额+ 冻结 -- 可用+
                //发布任务金额返还   总余额+ 冻结 -- 可用+
                //佣金返还   总余额+ 冻结 -- 可用+
                //营销红包用户退群返还（群-已删除）  总余额+ 冻结-- 可用+
                //领取营销红包  总余额+ 冻结-- 可用+
                //创建营销红包（余额创建）取消红包返还  总余额+ 冻结-- 可用+
                //充值余额   总余额+ 冻结 -- 可用+
                record(userId, type.getVal(), money, money, BigDecimal.ZERO, money, referId, memo);
                break;
            case WITHDRAW_FAIL:
            case RETURN_PACKET:
            case PACKET_SALE_BACK:
            case PACKET_MIXUAN_BACK:
            case PACKET_MIXUAN_TERMINATE_BACK:
            case PACKET_SALE_GET_FREEZE_NOT:
            case PACKET_SALE_GET_SUCCESS:
                //领取商品返利（审核通过）   总余额-- 冻结- 可用+
                //营销红包可提现（群-已删除）  总余额-- 冻结- 可用+
                //创建营销红包（余额创建）审核未通过返还  总余额-- 冻结- 可用+
                //超时返回可用余额  从冻结余额返回到可支配余额  总余额-- 冻结- 可用+
                //提现失败  从冻结余额返回到可支配余额  总余额-- 冻结- 可用+
                record(userId, type.getVal(), money, BigDecimal.ZERO, money.negate(), money, referId, memo);
                break;
            case PACKET_ADD:
                //红包充值 往冻结余额中充值  总余额+ 冻结+ 可用--   ---已停用
            case WEIXIN_CREATE_PACKET:
                //红包充值 微信 往冻结余额中充值  总余额+ 冻结+ 可用--
            case ALIPAY_CREATE_PACKET:
            case PACKET_SALE_GET_FREEZE:
            case MISSION_COMPLETE:
            case PACKET_SALE_GET_CHECK:
                //领取商品返利（待审核）  总余额+ 冻结+ 可用--
                //发布任务佣金  总余额+ 冻结+ 可用--
                //领取营销红包（群-已删除）  总余额+ 冻结+ 可用--
                //红包充值 支付宝 往冻结余额中充值  总余额+ 冻结+ 可用--
                record(userId, type.getVal(), money, money, money, BigDecimal.ZERO, referId, memo);
                break;
            case WITHDRAW:
            case WITHDRAW_TRANS:
            case RECEIVE_PACKET_CREATOR:
            case PACKET_SALE_CREATE:
            case PACKET_SALE_GET_FREEZE_USER_END:
                //营销红包退群扣除（群-已删除）  总余额- 冻结- 可用--
                //创建营销红包（余额创建）审核通过  总余额- 冻结- 可用--
                //从冻结余额中扣除  总余额- 冻结- 可用--
                //提现 直接从冻结余额中提取  总余额- 冻结- 可用--
                record(userId, type.getVal(), money, money.negate(), money.negate(), BigDecimal.ZERO, referId, memo);
                break;
            case WITHDRAW_APPLY:
                //提现申请  从可提现提往冻结  总余额-- 冻结+ 可用-
            case CREATE_PACKET:
                //从可用余额中扣除金额到冻结余额中去 总余额-- 冻结+ 可用-
            case PACKET_SALE_CHECK:
            case PACKET_MIXUAN_CHECK:
                //创建营销红包（余额创建）待审核  总余额-- 冻结+ 可用-
                record(userId, type.getVal(), money, BigDecimal.ZERO, money, money.negate(), referId, memo);
                break;
            case BACK_WITHDRAW:
            case MISSION:
            case MISSION_COMMISSION:
            case VIDEO_PUBLISH_DELETE:
            case CREATE_PACKET_MANGHE:
            // 用户开通初级合伙人 总余额- 冻结-- 可用-
            case USER_OPENS_MEMBERSHIP:
            // 用户开通中级合伙人 总余额- 冻结-- 可用-
            case USER_OPENS_MEMBERSHIP_INTERMEDIATE:
            // 用户开通高级合伙人 总余额- 冻结-- 可用-
            case USER_OPENS_MEMBERSHIP_SUPREME:
            // 用户开通终级合伙人 总余额- 冻结-- 可用-
            case USER_OPENS_MEMBERSHIP_ULTIMATE:
                // 用户支付商城订单
            case USER_PAYMENT_MALL_ORDER:
                // 用户余额兑换积分商城商品
            case USER_EXCHANGE_MALL_GOODS:
                //扣除余额 总余额- 冻结-- 可用-
                //发布任务佣金  总余额- 冻结-- 可用-
                //发布任务  总余额- 冻结-- 可用-
                //系统提现 直接从可用余额中提取  总余额- 冻结-- 可用-
                record(userId, type.getVal(), money, money.negate(), BigDecimal.ZERO, money.negate(), referId, memo);
                break;
            case VIP_ADD:
//                //更新用户会员积分
//                int integer = money.multiply(new BigDecimal("100")).intValue();
//                updateDetail(IntegralType.PAY_ADD, String.valueOf(referId), integer, userId);
                break;
            default:
        }
    }

    private void updateDetail(IntegralType type, String referId, Integer score, Long userId) {

        //增加记录
        UserIntegralDetail detail = new UserIntegralDetail();
        detail.setIntegral(score);
        detail.setReferType(type.getVal());
        detail.setMemo(type.getDesc());
        detail.setUserId(userId);
        detail.setReferId(referId);

        userIntegralDetailMapper.insertSelective(detail);

        //增加积分值
        userMapper.addIntegral(score, userId);

    }

    @Override
    public void updatePassword(Long userId, String password) {
        UserBalance balance = new UserBalance();
        balance.setPassword(MD5Util.shaEncode(password));

        Example update = new Example(UserBalance.class);
        update.createCriteria().andEqualTo("userId", userId);
        userBalanceMapper.updateByExampleSelective(balance, update);
    }

    @Override
    public void checkPassword(Long userId, String password) {
        UserBalance balance = selectByUserId(userId);
        String loginCountStr = redisService.getVal("pwd_c_" + userId);
        int loginCount = 0;
        int errCount = 0;
        if (Objects.nonNull(loginCountStr)) {
            loginCount = Integer.parseInt(loginCountStr);
        }
        loginCount++;
        if (loginCount > 5) {
            String lastTime = redisService.getVal("pwd_etime_" + userId);
            String errCountStr = redisService.getVal("pwd_ecount_" + userId);
            if (Objects.nonNull(errCountStr)) {
                errCount = Integer.parseInt(errCountStr);
            }
            if (Objects.isNull(lastTime)) {
                errCount++;
                redisService.setVal("pwd_etime_" + userId, String.valueOf(System.currentTimeMillis()));
                redisService.setVal("pwd_ecount_" + userId, String.valueOf(errCount));
                Contracts.assertTrue(false, "错误次数过多，请" + (errCount * 5) + "分钟后再试");
            } else {
                long lastT = Long.parseLong(lastTime);
                if (System.currentTimeMillis() - lastT < (long) errCount * 300000) {
                    Contracts.assertTrue(false, "错误次数过多，请" + (errCount * 5) + "分钟后再试");
                } else {
                    loginCount = 1;
                    redisService.delVal("pwd_c_" + userId);
                    redisService.delVal("pwd_etime_" + userId);
                }
            }

        }
        if (!MD5Util.shaEncode(password).equals(balance.getPassword())) {
            redisService.setVal("pwd_c_" + userId, String.valueOf(loginCount));
            Contracts.assertTrue(false, YiChatMsgCode.SYSTEM_USER_BALANCE_ACCOUNT_PASSWORD_ERROR.msg());
        } else {
            redisService.delVal("pwd_c_" + userId);
            redisService.delVal("pwd_ecount_" + userId);
            redisService.delVal("pwd_etime_" + userId);
        }
    }

    @Override
    public UserBalance selectByUserId(Long userId) {
        Example select = new Example(UserBalance.class);
        select.createCriteria().andEqualTo("userId", userId);
        UserBalance balance = userBalanceMapper.selectOneByExample(select);
        Contracts.assertNotNull(balance, YiChatMsgCode.SYSTEM_USER_BALANCE_ACCOUNT.msg());
        Contracts.assertTrue(balance.getStatus().compareTo(FsConst.Status.EFFECT) == 0, YiChatMsgCode.SYSTEM_USER_BALANCE_ACCOUNT_STATUS.msg());
        return balance;
    }

    @Override
    public String queryDetailsLastTime(Long userId) {
        return userBalanceDetailMapper.queryDetailsLastTime(userId);
    }

    @Override
    public void record(Long userId, Integer type, BigDecimal money, BigDecimal balance, BigDecimal freezeMoney, BigDecimal incomeMoney, Long referId, String desc) {

        synchronized (SysInternPool.INSTANCE.internUid(userId)) {
            UserBalance bb = selectByUserId(userId);

            //添加流水记录
            UserBalanceDetail detail = new UserBalanceDetail();
            detail.setUserId(userId);
            detail.setBalanceId(bb.getId());
            detail.setMoney(money);
            detail.setbFreeze(bb.getFreezeBalance());
            detail.setbIncome(bb.getIncomeBalance());
            detail.setbBalance(bb.getBalance());

            detail.setaBalance(bb.getBalance().add(balance));
            detail.setaFreeze(bb.getFreezeBalance().add(freezeMoney));
            detail.setaIncome(bb.getIncomeBalance().add(incomeMoney));

            detail.setMemo(desc);

            detail.setReferId(referId);
            detail.setType(type);
            int i = userBalanceDetailMapper.insertSelective(detail);
            Contracts.assertTrue(i == 1, YiChatMsgCode.SYSTEM_ERROR.msg());


            //更新余额
            int ii = userBalanceMapper.updateBalance(userId, balance, freezeMoney, incomeMoney);
            Contracts.assertTrue(ii == 1, YiChatMsgCode.SYSTEM_ERROR.msg());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Pair<Long, BigDecimal> sumUserBalance() {
        BigDecimal incomeBalance = userBalanceMapper.sumTotal();
        Example example = new Example(UserBalanceDetail.class);
        example.setOrderByClause("id desc limit 1");
        UserBalanceDetail detail = userBalanceDetailMapper.selectOneByExample(example);
        return Pair.of(detail.getId(), incomeBalance);
    }

    @Override
    public FsResponse selectList(Integer type, Long userId, String ctime) {

        Example select = new Example(UserBalanceDetail.class);
        Example.Criteria criteria = select.createCriteria();
        criteria.andEqualTo("userId", userId);

        if (StringUtils.isNotBlank(ctime)) {
            criteria.andCondition("DATE_FORMAT(ctime,'%Y-%m-%d') = ", ctime);
        }
        if (Objects.nonNull(type)) {
            //支出
            if (type == 0) {
                criteria.andIn("type", Arrays.asList(BalanceType.VIDEO_PUBLISH_DELETE.getVal(),
                        BalanceType.CREATE_PACKET.getVal(),
                        BalanceType.VIP_ADD.getVal(),
                        BalanceType.PACKET_MIXUAN_CHECK.getVal(),
                        BalanceType.CREATE_PACKET_MANGHE.getVal(),
                        BalanceType.WITHDRAW.getVal(),
                        BalanceType.WITHDRAW_TRANS.getVal(),
                        BalanceType.BACK_WITHDRAW.getVal(),
                        BalanceType.USER_OPENS_MEMBERSHIP.getVal(), // 开通初级合伙人
                        BalanceType.USER_OPENS_MEMBERSHIP_INTERMEDIATE.getVal(), // 开通中级合伙人
                        BalanceType.USER_OPENS_MEMBERSHIP_SUPREME.getVal(), // 开通高级合伙人
                        BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE.getVal(), // 开通终级合伙人
                        BalanceType.USER_PAYMENT_MALL_ORDER.getVal(), // 用户商城支付
                        BalanceType.USER_EXCHANGE_MALL_GOODS.getVal(), // 用户兑换积分商城商品
                        BalanceType.PACKET_SALE_CHECK.getVal(),
                        BalanceType.PACKET_SALE_GET_FREEZE_USER_END.getVal()));
            }
            //收入
            else {
                criteria.andIn("type", Arrays.asList(
                        BalanceType.VIDEO_COMMENT.getVal(),
                        BalanceType.INTEGRAL_EXCHANGE_BALANCE.getVal(), // 积分兑换余额
                        BalanceType.PACKET_MIXUAN_TERMINATE_BACK.getVal(),
                        BalanceType.PACKET_FANLI_INVITE_GET.getVal(),
                        BalanceType.USER_INVITE.getVal(), BalanceType.VIDEO_PRAISE.getVal(), BalanceType.VIDEO_PLAY.getVal(), BalanceType.VIDEO_PACKET.getVal(), BalanceType.VIP_PACKET_RECEIVE.getVal(), BalanceType.PACKET_SALE_GET_SUCCESS.getVal(), BalanceType.PACKET_FANLI_GET.getVal(), BalanceType.PACKET_MIXUAN_BACK.getVal(), BalanceType.VIDEO_PUBLISH.getVal(), BalanceType.RECEIVE_PACKET.getVal(), BalanceType.RETURN_PACKET.getVal(), BalanceType.ADD.getVal(), BalanceType.SIGN.getVal(), BalanceType.BACK_ADD.getVal(), BalanceType.PACKET_SALE_GET.getVal(), BalanceType.PACKET_SALE_BACK.getVal(), BalanceType.PACKET_SALE_TERMINATE_BACK.getVal(), BalanceType.PACKET_SALE_GET_FREEZE.getVal(), BalanceType.PACKET_SALE_GET_FREEZE_NOT.getVal(), BalanceType.PACKET_SALE_GET_FREEZE_OWNER_END.getVal()));
            }
        }
        // 查询全部类型-收入和支出
        else {
            criteria.andIn("type", Arrays.asList(BalanceType.VIDEO_COMMENT.getVal(),
                    BalanceType.PACKET_MIXUAN_TERMINATE_BACK.getVal(),
                    BalanceType.INTEGRAL_EXCHANGE_BALANCE.getVal(), // 积分兑换余额
                    BalanceType.USER_INVITE.getVal(),
                    BalanceType.PACKET_FANLI_INVITE_GET.getVal(),
                    BalanceType.VIP_ADD.getVal(), BalanceType.VIDEO_PRAISE.getVal(),
                    BalanceType.CREATE_PACKET_MANGHE.getVal(), BalanceType.VIDEO_PACKET.getVal(),
                    BalanceType.VIP_PACKET_RECEIVE.getVal(), BalanceType.VIDEO_PUBLISH.getVal(),
                    BalanceType.PACKET_SALE_GET_SUCCESS.getVal(), BalanceType.PACKET_FANLI_GET.getVal(),
                    BalanceType.PACKET_MIXUAN_CHECK.getVal(), BalanceType.PACKET_MIXUAN_BACK.getVal(),
                    BalanceType.VIDEO_PUBLISH_DELETE.getVal(), BalanceType.CREATE_PACKET.getVal(),
                    BalanceType.WITHDRAW_TRANS.getVal(),BalanceType.WITHDRAW, BalanceType.RECEIVE_PACKET.getVal(),
                    BalanceType.RETURN_PACKET.getVal(), BalanceType.ADD.getVal(),
                    BalanceType.SIGN.getVal(), BalanceType.BACK_ADD.getVal(),
                    BalanceType.USER_OPENS_MEMBERSHIP.getVal(), // 开通初级合伙人
                    BalanceType.USER_OPENS_MEMBERSHIP_INTERMEDIATE.getVal(), // 开通中级合伙人
                    BalanceType.USER_OPENS_MEMBERSHIP_SUPREME.getVal(), // 开通高级合伙人
                    BalanceType.USER_OPENS_MEMBERSHIP_ULTIMATE.getVal(), // 开通终级合伙人
                    BalanceType.USER_PAYMENT_MALL_ORDER.getVal(), // 用户商城支付
                    BalanceType.USER_EXCHANGE_MALL_GOODS.getVal(), // 用户兑换积分商城商品
                    BalanceType.BACK_WITHDRAW.getVal(), BalanceType.PACKET_SALE_CHECK.getVal(),
                    BalanceType.PACKET_SALE_BACK.getVal(), BalanceType.PACKET_SALE_TERMINATE_BACK.getVal(),
                    BalanceType.PACKET_SALE_GET_FREEZE_USER_END.getVal(), BalanceType.PACKET_SALE_GET.getVal(),
                    BalanceType.PACKET_SALE_GET_FREEZE.getVal(), BalanceType.PACKET_SALE_GET_FREEZE_NOT.getVal(),
                    BalanceType.PACKET_SALE_GET_FREEZE_OWNER_END.getVal()));
        }

        select.setOrderByClause(" ctime desc");
        return DtoChangeUtils.getPageList(userBalanceDetailMapper.selectByExample(select), v -> {
            BalanceListDto dto = new BalanceListDto();
            dto.setCtime(DateUtils.formatDate(v.getCtime(), "yyyy-MM-dd HH:mm:ss"));
            dto.setDateDesc(DateUtils.formatDate(v.getCtime(), "MM-dd"));
            dto.setMemo(v.getMemo());
            dto.setMoney(v.getMoney());
            dto.setType(v.getType());
            dto.setId(v.getId());
            dto.setReferId(v.getReferId());
            dto.setBalance(v.getaIncome());
            dto.setMoneyDesc(BalanceType.valOf(v.getType()).getDirect() + v.getMoney() + FsConst.UNIT);

            // 查询资金类型为红包
            Integer balanceType = v.getType();
            // 2 是发红包  3 是领取红包
            if (balanceType == BalanceType.RECEIVE_PACKET.getVal() || balanceType == BalanceType.CREATE_PACKET.getVal()) {

                // 查询详情
                Long packetId = v.getReferId();
                Packet packet = packetMapper.selectByPrimaryKey(packetId);

                if (null != packet) {
                    Long sendUserId = packet.getUserId();
                    // 查询接发人的昵称
                    User sendUser = userMapper.selectByPrimaryKey(sendUserId);
                    if (null != sendUser) {
                        dto.setSendUserId(sendUserId);
                        dto.setSendUserName(sendUser.getNick());
                    }

                    // type 0 是单聊 1是群聊
                    Integer packetType = packet.getType();

                    // 单聊或者群专属红包或者转账的类型
                    if (0 == packetType || 3 == packetType || 2 == packetType) {
                        Long receiveUserId = packet.getReceiveUser();
                        dto.setReceiveUserId(receiveUserId);
                        User receiveUser = userMapper.selectByPrimaryKey(receiveUserId);
                        if (null != receiveUser) {
                            dto.setReceiveUserName(receiveUser.getNick());
                        }

                    }
                    // 群聊
                    if (1 == packetType) {
                        Long groupId = packet.getGroupId();
                        RcGroups groups = groupsMapper.selectGroupById(groupId);

                        // 如果群组为空说明该群组已经被解散了  需要查询备用表的群组信息
                        if (null == groups) {
                            RcGroupsDismiss groupsDismiss = groupsDismissMapper.selectGroupDismissById(groupId);
                            if (null != groupsDismiss) {
                                dto.setReceiveUserId(groupId);
                                dto.setReceiveUserName(groupsDismiss.getName());
                            }
                        }else {
                            dto.setReceiveUserId(groupId);
                            dto.setReceiveUserName(groups.getName());
                        }

                    }

                    dto.setReceiveState(packet.getStatus());
                    dto.setReceiveOverState(packet.getOverStatus());
                    dto.setPacket(packet);
                }


//                PacketReceiveInfoDto receiveInfo = packetMapper.selectReceiveCount(null, v.getUserId());
//                if (null != receiveInfo) {
//                    PacketDto packet = new PacketDto();
//                    packet.setMoney(receiveInfo.getMoney());
//                    packet.setType(receiveInfo.getType());
//                    packet.setSendUser(receiveInfo.getSendUser());
//                    dto.setPacket(packet);
//                }
            }
            return dto;
        });
    }


    @Override
    public List<UserBalanceDetail> selectSaleDisList(Integer limit) {
        Example select = new Example(UserBalanceDetail.class);

        Example.Criteria criteria = select.createCriteria();

        criteria.andEqualTo("type", BalanceType.PACKET_SALE_GET_SUCCESS.getVal());
        select.setOrderByClause(" id desc limit 20");
        return userBalanceDetailMapper.selectByExample(select);
    }

    @Override
    public synchronized FsResponse checkWithdraw(Integer id, Integer status, String reason) {
        UserWithdraw withdraw = userWithdrawMapper.selectByPrimaryKey(id);
        if (Objects.nonNull(withdraw) && withdraw.getStatus() == 0) {
            //通过
            if (status == 1) {
                status = 4;
                withdraw.setStatus(status);
                withdraw.setRefuseReason(reason);
                withdraw.setCheckTime(new Date());
                userWithdrawMapper.updateByPrimaryKey(withdraw);
                Integer type = withdraw.getType();
                if (type == 0) {
                    FsResponse response = payService.sandWithDraw(withdraw.getId(), withdraw.getUserId(), withdraw.getBankNumber(), withdraw.getFutureMoney());
//                    if (!response.isSuccess()) {
//                        //处理失败，不会异步
//                        balanceService.doWithdraw(2, response.getMsg(), withdraw);
//                    } else {
//                        //由异步接管checkWithdrawForHj
//                    }
                } else if (type == 1) {
                    FsResponse res = xsPayService.xspayWithDraw(withdraw.getUserId(), withdraw.getBankNumber(), withdraw.getFutureMoney());
                    if (!res.isSuccess()) {
                        balanceService.doWithdraw(2, res.getMsg(), withdraw);
                    } else {
                        balanceService.doWithdraw(1, null, withdraw);
                    }

                }

            } else if (status == 2) { //拒绝
                //余额变更
                balanceService.doWithdraw(status, reason, withdraw);
            } else {
                //线下转账
                balanceService.doWithdraw(status, reason, withdraw);
            }
        }

        return FsResponseGen.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doWithdraw(Integer status, String reason, UserWithdraw withdraw) {
        BalanceType balanceType;
        String memo, pushContent;
        boolean needBack = false;
        if (status == 1) {
            balanceType = BalanceType.WITHDRAW;
            memo = "提现成功";
            pushContent = "提现成功，提现金额【" + NumberUtils.halfTwo(withdraw.getMoney()) + FsConst.UNIT + "】";
        } else if (status == 2) {
            needBack = true;
            balanceType = BalanceType.WITHDRAW_FAIL;
            memo = "提现失败";
            pushContent = "提现申请被拒绝，拒绝理由【" + reason + "】";
        } else {
            needBack = true;
            balanceType = BalanceType.WITHDRAW_TRANS;
            memo = "提现成功";
            pushContent = "提现成功-已转账，提现金额【" + NumberUtils.halfTwo(withdraw.getMoney()) + FsConst.UNIT + "】";
        }
        update(withdraw.getUserId(), balanceType, withdraw.getMoney(), withdraw.getId().longValue(), memo);
        pushService.sendServiceSingle(0, withdraw.getBankNumber(), DateUtils.formatDate(withdraw.getCheckTime()), withdraw.getId().longValue(), withdraw.getUserId(), "提现消息", withdraw.getMoney(), pushContent, false);

        withdraw.setStatus(status);
        withdraw.setRefuseReason(reason);
        withdraw.setCheckTime(new Date());
        userWithdrawMapper.updateByPrimaryKey(withdraw);

        try {
            String xsBalance = redisService.getVal("xs_balance");
            String hjBalance = redisService.getVal("hj_balance");
            if (xsBalance != null && hjBalance != null && needBack) {
                if (withdraw.getType() == 0) {
                    BigDecimal hjBalanceBig = new BigDecimal(hjBalance);
                    redisService.setVal("hj_balance", hjBalanceBig.subtract(withdraw.getMoney()).toString());
                } else if (withdraw.getType() == 1) {
                    BigDecimal xsBalanceBig = new BigDecimal(xsBalance);
                    redisService.setVal("xs_balance", xsBalanceBig.subtract(withdraw.getMoney()).toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public synchronized FsResponse checkWithdrawForHj(Integer userId, Integer status, String reason) {
//        String[] ids = orderCode.split("_");
//        Integer id = Integer.valueOf(ids[0]);
        UserWithdraw withdraw = userWithdrawMapper.selectByPrimaryKey(userId);
        if (Objects.nonNull(withdraw) && withdraw.getStatus() == 4) {
            balanceService.doWithdraw(status, reason, withdraw);
        }

        return FsResponseGen.success();
    }


    @Override
    public Long createTradeRecord(Long userId, String tradeId, BigDecimal money, PayType payType, Integer tradeType) {

        UserTrade trade = new UserTrade();
        trade.setMoney(money);
        trade.setTradeNo(tradeId);
        trade.setUserId(userId);
        trade.setPayType(payType.getVal());
        trade.setType(tradeType);
        trade.setStatus(0);
        trade.setCtime(new Date());

        userTradeMapper.insertUseGeneratedKeys(trade);

        return trade.getId();
    }

    @Override
    public UserTrade selectTradeByTradeNo(String tradeNo) {
        Example example = new Example(UserTrade.class);
        example.createCriteria().andEqualTo("tradeNo", tradeNo);
        return userTradeMapper.selectOneByExample(example);
    }

    @Override
    public void completeTrade(Long id) {
        UserTrade trade = new UserTrade();
        trade.setId(id);
        trade.setStatus(1);

        userTradeMapper.updateByPrimaryKeySelective(trade);
    }

    @Override
    public BigDecimal selectTotalByType(Long userId, BalanceType type) {

        return userBalanceDetailMapper.sumTotalByType(userId, type.getVal(), null, null);
    }

    @Override
    public List<SaleChartItem> selectChartList() {
        return userBalanceDetailMapper.selectChartList();
    }

    @Override
    public Long selectOrderNum(BigDecimal money) {

        return userBalanceDetailMapper.selectChartOrderNum(money);
    }

    @Override
    public UserBalanceDetail selectDetailByReferId(Long missionId, BalanceType mission) {
        Example example = new Example(UserBalanceDetail.class);
        example.createCriteria().andEqualTo("referId", missionId).andEqualTo("type", mission.getVal());
        example.setOrderByClause("  id desc limit 1");
        return userBalanceDetailMapper.selectOneByExample(example);
    }

}
